#ifndef __UGEN_BUSINESS_C__
#define __UGEN_BUSINESS_C__
#include "ugen_feature.h"
#include "ugen_business.h"
#include "ugen_config.h"

unsigned char FACTORY_TEST_FLAG = 0; //标记为1为时在执行产测2

static ugen_cmd_device_table_t cmd_device_table[] = {
    /* Universal test firmware (These functions are in the ugen_main file) */
    {NETWORK, ugen_start_ap_config},     /* 配网 */
    {GET_STATE, ugen_wifi_state_reply},  /* mcu主动查询状态 */
    {RESET, ugen_reset_start},           /* 初始化 */
    {HEARTBEAT, hertbeat_reply},         /* 心跳 */
    {UPGRAND_TIME, ugen_send_timeStamp}, /* 时间校准 */
    {FACTORY, ugen_factory_test},        /* 产测 */
#ifdef __BUSINESS_CODE_SUPPORT__
    /* Business agreement (These functions are in the ugen_business file) */
    {SETPROPRETY, set_property_reply},   /* 下发属性 */
    {UPPROPRETY, get_ugen_config_value}, /* 上报属性 */
    {UPEVENT, get_ugen_config_value},    /* 上报事件 */
#endif //__BUSINESS_CODE_SUPPORT__
    {0xFF, NULL} /* must be at the end */
};

/**
  * @brief  MCU上报处理
  * @param  data 数据包
  * @param  len 数据包长度
  * @return none
  * @note   none
  */
void ugen_uart_recv_handle(uint8_t *data, uint32_t len)
{
    LOG_TRACE("ugen_uart_recv_handle start len->%d\n", len);
    TRACE_BINARY(data, len);

    uint8_t i = 0;
    uint8_t uart_cmd[UART_DATA_LEN] = {0};
    uint32_t uart_cmd_len = len > UART_DATA_LEN ? UART_DATA_LEN : len;
    DeviceCMD_t cmd_data;
    cmd_data.head = *(data);            //指令头
    cmd_data.msg_len = *(data + 2) + 3; //指令长度
    cmd_data.type = *(data + 3);        //CMD type

    if (cmd_data.head != MCU_CMD_HEAD)
    {
        LOG_TRACE("CMD head error!");
        return;
    }
    if (cmd_data.msg_len < 5)
    {
        LOG_TRACE("no cmd_type");
        return;
    }
    //校验位检查
    uint8_t check_num = check_sum(data, len);
    LOG_TRACE("===============CHECK_NUM:%d=============", check_num);
    if (check_num != data[1])
    {
        LOG_TRACE("check value faile");
        return;
    }

    LOG_TRACE("cmd type is :%d ==========", cmd_data.type);
    LOG_TRACE("uart_cmd:");
    memcpy(uart_cmd, data, uart_cmd_len);
    TRACE_BINARY(uart_cmd, uart_cmd_len);
    while (cmd_device_table[i].command != 0xff)
    {
        if (cmd_data.type == cmd_device_table[i].command)
        {
            if (cmd_device_table[i].ugen_cmd_cb != NULL)
                cmd_device_table[i].ugen_cmd_cb(uart_cmd, uart_cmd_len);
            break;
        }
        LOG_TRACE("cmd_device_table command:%x ===== ", cmd_device_table[i].command);
        LOG_TRACE("cmd_data type:%x", cmd_data.type);
        i++;
    }
}

/************************************************************************************
 *                                 Business function                                   *
 ************************************************************************************/
#ifdef __BUSINESS_CODE_SUPPORT__
/* 获取协议配置 */
ugen_config *get_ugen_config(void)
{
    return &currency_config;
}

/* 下发属性设置回复 */
void set_property_reply(uint8_t *data, uint32_t len)
{
    int res = data[4];
    if (res)
        LOG_TRACE("set success");
    else
        LOG_TRACE("set false");
}

/* 上报结果回复 */
void ugen_up_reply(int res, uint8_t msg_type)
{
    uint8_t reply_buf[5] = {MODEL_CMD_HEAD, 0x03, 0x02, UPPROPRETY, 0x01};
    if (!res)
        reply_buf[4] = 0x00; //00失败;01是成功
    if (msg_type == UPEVENT)
        reply_buf[3] = UPEVENT;
    reply_buf[1] = check_sum(reply_buf, 5);
    ugen_uart_send(reply_buf, 5);
}

/* 添加键值 */
static int *ugen_add_value(uint8_t type, cJSON *root, char *Now_name, uint8_t *Now_value, uint8_t len) //填入json数据;
{
    switch (type)
    {
    case TYPE_BOOL:
        cJSON_AddNumberToObject(root, Now_name, Now_value[0]);
        break;
    case TYPE_UINT8_T:
        cJSON_AddNumberToObject(root, Now_name, Now_value[0]);
        break;
    case TYPE_UINT16_T:
        cJSON_AddNumberToObject(root, Now_name, (Now_value[0] << 8) + Now_value[1]);
        break;
    case TYPE_UINT32_T:
        cJSON_AddNumberToObject(root, Now_name, ((Now_value[0] << 24) + (Now_value[1] << 16) + (Now_value[2] << 8) + Now_value[3]));
        break;
    case TYPE_INT8_T:
        cJSON_AddNumberToObject(root, Now_name, 0 - Now_value[0]);
        break;
    case TYPE_INT16_T:
        cJSON_AddNumberToObject(root, Now_name, 0 - ((Now_value[0] << 8) + Now_value[1]));
        break;
    case TYPE_INT32_T:
        cJSON_AddNumberToObject(root, Now_name, 0 - ((Now_value[0] << 24) + (Now_value[1] << 16) + (Now_value[2] << 8) + Now_value[3]));
        break;
    case TYPE_STRING:
    {
        char valuestr[60];
        int valuestr_len = 0;
        LOG_TRACE("TYPE_STRING :");
        for (int i = 0; i < len; i++)
        {
            valuestr_len = strlen(valuestr);
            snprintf(valuestr + valuestr_len, (60 - valuestr_len), "%d", Now_value[i]);
            LOG_TRACE("%d", Now_value[i]);
        }
        LOG_TRACE("\nTYPE_STRING=:%s\n", valuestr);
        cJSON_AddStringToObject(root, Now_name, (char *)valuestr);
        break;
    }
    default:
        break;
    }
}

uint32_t sum_up_pro = 0;
uint32_t sum_up_suc = 0;
/* 更新键值 */
static int *ugen_up_value(uint8_t msg_type, cJSON *root, char *event_id)
{
    LOG_TRACE("ugen_up_value start");
    user_example_ctx_t *user_example_ctx = user_example_get_ctx();
    char *payload = "NULL";
    int res = 0;
    if (msg_type == UPPROPRETY) //属性
    {
        payload = cJSON_Print(root);
        res = IOT_Linkkit_Report(user_example_ctx->master_devid, ITM_MSG_POST_PROPERTY, (unsigned char *)payload, strlen(payload)); //上报
    }
    else //事件
    {
        LOG_TRACE("up start ;event_id =%s", event_id);
        payload = cJSON_PrintUnformatted(root);
        res = IOT_Linkkit_TriggerEvent(user_example_ctx->master_devid, event_id, strlen(event_id), (unsigned char *)payload, strlen(payload));
    }
    LOG_TRACE("payload=%s;;res =%d", payload, res);
    aos_free(payload); //释放内存

    ugen_up_reply(res, msg_type); //回复上报结果
    sum_up_pro++;
    if (res)
    {
        //sum_up_suc ++;
        LOG_TRACE("----->up_true sum_up_pro=%d;;sum_up_suc=%d\r\n", sum_up_pro, sum_up_suc);
    }
    else
        LOG_TRACE("----->up_false\r\n");
    
    return res;
}

static uint8_t *set_cloude_cmd(ugen_config NowConfig, cJSON *item, uint8_t *cloude_date_len)
{
    LOG_TRACE("ugen_uart_send_property start\n");
    uint8_t *cloude_buf = (uint8_t *)aos_malloc(sizeof(uint8_t) * RECV_UART_DATA_MAXLENGTH);
    uint8_t value_data_len = 0;
    switch (NowConfig.value)
    {
    case TYPE_BOOL:
        value_data_len = 1;
        break;
    case TYPE_UINT8_T:
        value_data_len = 1;
        break;
    case TYPE_UINT16_T:
        value_data_len = 2;
        break;
    case TYPE_UINT32_T:
        value_data_len = 4;
        break;
    case TYPE_INT8_T:
        value_data_len = 1;
        break;
    case TYPE_INT16_T:
        value_data_len = 2;
        break;
    case TYPE_INT32_T:
        value_data_len = 4;
        break;
    case TYPE_STRING:
    {
        uint8_t *value_string = (uint8_t *)(item->valuestring); //get_str_value(data,NowConfig[0].name);
        uint8_t value_string_len = strlen(value_string);
        LOG_TRACE("string =%s;;string_len =%d\n", value_string, value_string_len);
        memcpy((cloude_buf + 3), value_string, value_string_len);
        LOG_TRACE("buf =%s\n", (uint8_t *)cloude_buf);
        value_data_len = value_string_len;
    }
    default:
        return 0;
    }

    if ((value_data_len == 0) && (value_data_len > (RECV_UART_DATA_MAXLENGTH - 4)))
    {
        LOG_TRACE("len error\n");
        return NULL;
    }
    *cloude_date_len += value_data_len + 3;
    // LOG_TRACE("*cloude_date_len =%d;;value_data_len=%d;;\n",*cloude_date_len,value_data_len);
    cloude_buf[0] = *cloude_date_len;
    cloude_buf[1] = (NowConfig.data) >> 8;
    cloude_buf[2] = (NowConfig.data) & 0xFF;
    if ((NowConfig.value != TYPE_STRING))
    {
        int32_t valueint = item->valueint; //获取属性值 1;//
        LOG_TRACE("valueint=%d", valueint);
        uint8_t value_data[8] = {0};
        memcpy(value_data, &valueint, value_data_len);
        for (int i = 0; i < value_data_len; i++)
        {
            cloude_buf[value_data_len + 2 - i] = value_data[i];
            //LOG_TRACE("cloude_buf[value_data_len+2-i] ==%d",cloude_buf[value_data_len+2-i]);
        }
    }
    return cloude_buf;
}

/* MCU上报指令解析上报 */
void get_ugen_config_value(uint8_t *data, uint8_t len)
{
    LOG_TRACE("get_ugen_config_value size_NowConfig--->:%d\n", sizeof(ugen_config));
    ugen_config *currency_config = get_ugen_config();
    uint8_t NowConfig_sum = 0;      //指令含有属性事件数量
    uint8_t msg_len = data[2];      //消息体总长度
    uint8_t msg_type = data[3];     //上报类型
    uint8_t property_len = data[4]; //单个属性或事件长度
    uint8_t *p = (data + 4);        //总循环的指针开始位置
    uint8_t check_config = 0;       //事件或属性在结构体位置
    LOG_TRACE("data[4]=%d;; *p =%d\n", property_len, *p);
    //上报的json
    cJSON *root;
    root = cJSON_CreateObject(); //a,b,1 {"a":}
    char *event_id = NULL;

    while (((msg_len - 1) > 0) && (currency_config[check_config].name != NULL)) //属性查找完没有或到长度最后结束
    {
        //LOG_TRACE("(msg_len - 1)=%d;;currency_config[check_config].name =:%s\n",(msg_len - 1),currency_config[check_config].name);
        if (((*(p + 1)) << 8) + (*(p + 2)) == (currency_config[check_config].data)) //判断action
        {
            //LOG_TRACE("set pro :%d;;check_config=%d\n",NowConfig_sum,check_config);
            if (currency_config[check_config].value != TYPE_EVENT)
            {
                // uint8_t * Now_value = p+3;//属性值指针
                // char * Now_name = currency_config[check_config].name;
                ugen_add_value(currency_config[check_config].value, root, currency_config[check_config].name, (p + 3), (property_len - 3));
            }
            else
            {
                event_id = currency_config[check_config].name;
            }
            p += property_len;       //总循环指针跳转到下一个参数
            msg_len -= property_len; //剩下的总长度
            property_len = *p;       //len为下一个参数的字节长度
            NowConfig_sum++;
            check_config = 0;
            continue;
            // break;
        }
        check_config++;
    }

    if (NowConfig_sum != 0)
    {
        ugen_up_value(msg_type, root, event_id); //上报云端
    }
    else
    {
        LOG_TRACE("NowConfig_sum == 0,not find");
        ugen_up_reply(NowConfig_sum, msg_type);
    }
    cJSON_Delete(root); //释放内存
    return 0;
}

uint32_t sum_cloude = 0;
uint32_t sum_suc = 0;
/* Cloud下发指令解析下发 */
void ugen_analysis_cloude_cmd(uint8_t *data, uint8_t len)
{
    LOG_TRACE("ugen_cloud_recv_handle %s --->len %d\n", data, len);
    LOG_TRACE("ugen_analysis_cloude_cmd :len=%d\n", len);
    ugen_config *currency_config = get_ugen_config();
    // uint8_t uart_buf[RECV_UART_DATA_MAXLENGTH] = {DEVICE_CMD_HEAD,0xFF,0xFF,SETPROPRETY};
    uint8_t *uart_buf = (uint8_t *)aos_malloc(sizeof(uint8_t) * RECV_UART_DATA_MAXLENGTH);
    if (uart_buf == NULL)
    {
        LOG_TRACE("uart_buf is NULL\n");
        return 0;
    }

    uint8_t total_len = 4;       //发送指令总长度
    uint8_t cloude_date_len = 0; //提取到属性的和标识的长度

    cJSON *root = NULL, *item = NULL;
    root = cJSON_Parse(data); //

    int i = 0;
    while ((currency_config[i].name != NULL))
    {
        if (strstr(data, (currency_config[i].name)))
        {
            LOG_TRACE("property_good;name =%s\n", (currency_config[i].name));
            item = cJSON_GetObjectItem(root, (currency_config[i].name));
            uint8_t *cloud_data = set_cloude_cmd(currency_config[i], item, &cloude_date_len);
            if ((total_len > RECV_UART_DATA_MAXLENGTH) && cloude_date_len)
            {
                LOG_TRACE("value error\n");
                break;
            }
            //LOG_TRACE("memcpy start cloude_date_len=%d;;uart_buf + total_len=%d;\n",cloude_date_len,*(uart_buf + total_len));
            memcpy(uart_buf + total_len, cloud_data, cloude_date_len);
            aos_free(cloud_data);
            total_len += cloude_date_len; //长度增加
            cloude_date_len = 0;
        }
        i++;
    }
    ++sum_cloude;
    if (total_len > 4)
    {
        ++sum_suc;
        printf("sum =%d,sucess=%d\n", sum_cloude, sum_suc);
        uart_buf[0] = MODEL_CMD_HEAD;
        uart_buf[3] = SETPROPRETY;
        uart_buf[2] = total_len - 3;
        uart_buf[1] = check_sum(uart_buf, total_len);
        ugen_uart_send(uart_buf, total_len);
#ifdef PROPERTY_AUTO_REPLY /*云端设置属性自动回复*/
        uart_buf[3] = UPPROPRETY;
        get_ugen_config_value(uart_buf, total_len);
#endif
    }
    else
        LOG_TRACE("ugen_cloud_recv_handle Not find attr type.\n");

    aos_free(uart_buf);
    cJSON_Delete(root);
    return 0;
}

#endif //__BUSINESS_CODE_SUPPORT__
/************************************************************************************
 *                                    End function                                     *
 ************************************************************************************/

#endif //__UGEN_BUSINESS_C__